package com.hit.aircraftwar.application;

import android.annotation.SuppressLint;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.media.MediaPlayer;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import androidx.annotation.NonNull;

import com.hit.aircraftwar.R;
import com.hit.aircraftwar.activity.LoginActivity;
import com.hit.aircraftwar.activity.MainActivity;
import com.hit.aircraftwar.activity.SignActivity;
import com.hit.aircraftwar.aircraft.AbstractAircraft;
import com.hit.aircraftwar.aircraft.Boss;
import com.hit.aircraftwar.aircraft.EliteEnemy;
import com.hit.aircraftwar.aircraft.HeroAircraft;
import com.hit.aircraftwar.basic.AbstractFlyingObject;
import com.hit.aircraftwar.bullet.AbstractBullet;
import com.hit.aircraftwar.bullet.Missile;
import com.hit.aircraftwar.bullet.MissileBoom;
import com.hit.aircraftwar.bullet.TrackBullet;
import com.hit.aircraftwar.creator.BombSupplyCreator;
import com.hit.aircraftwar.creator.Creator;
import com.hit.aircraftwar.creator.FireSupplyCreator;
import com.hit.aircraftwar.creator.HpSupplyCreator;
import com.hit.aircraftwar.dao.Record;
import com.hit.aircraftwar.dao.RecordsDAO;
import com.hit.aircraftwar.dao.RecordsDaoImpl;
import com.hit.aircraftwar.difficulty.DifficultyClass;
import com.hit.aircraftwar.difficulty.EasyDiff;
import com.hit.aircraftwar.difficulty.HardDiff;
import com.hit.aircraftwar.difficulty.MediumDiff;
import com.hit.aircraftwar.httputil.MyWsManager;
import com.hit.aircraftwar.service.MusicService;
import com.hit.aircraftwar.setter.ParameterSet;
import com.hit.aircraftwar.setter.TimeController;
import com.hit.aircraftwar.supply.AbstractSupply;
import com.hit.aircraftwar.supply.BombSupply;
import com.hit.aircraftwar.supply.FireSupply;
import com.hit.aircraftwar.supply.FireSupplyThread;
import com.hit.aircraftwar.supply.HpSupply;
import com.zhy.http.okhttp.OkHttpUtils;
import com.zhy.http.okhttp.callback.StringCallback;

import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;

@SuppressLint("ViewConstructor")
public class GameView extends SurfaceView implements SurfaceHolder.Callback, Runnable {

    private final SurfaceHolder surfaceHolder;
    private Canvas canvas;
    Paint paint = new Paint();
    private boolean isDrawing;

    private final HeroAircraft heroAircraft;
    private final List<AbstractAircraft> enemyAircrafts;
    private final List<AbstractBullet> heroBullets;
    private final List<AbstractBullet> enemyBullets;
    private final List<AbstractSupply> supplies;

    private int height;
    private int width;

    public static int score = 0;
    private int scoreIncrease = 0;

    private int time = 0;
    private int timeWithoutElite = 0;

    private final int timeInterval = 20;
    private Thread boomingThread;
    private TimeController boomingTimeController;
    private FireSupplyThread fireSupplyThread;
    private DifficultyClass difficultyClass = null;

    // 背景图片绘制的分界线坐标
    private int backgroundTop = 0;
    private Bitmap backgroundBitmap = null;
    // 线程池
    public static ScheduledThreadPoolExecutor executorService;

    //音乐播放
    private final Context context;
    private boolean hasBoss;
    private MusicService.MyBinder myBinder;
    private MediaPlayer player;
    private final RecordsDAO recordsDAO;
    private final Handler handler;
    /**
     * 周期（ms)
     * 指示子弹的发射、敌机的产生频率
     */
    private int cycleDuration = 600;
    private int cycleTime = 0;

    public GameView(Context context, Handler handler) {
        super(context);
        this.handler = handler;
        score = 0;
        hasBoss = false;
        ParameterSet.INSTANCE.setHasBoss(false);

        heroAircraft = HeroAircraft.getInstance();
        heroAircraft.restart();

        enemyAircrafts = new LinkedList<>();
        heroBullets = new LinkedList<>();
        enemyBullets = new LinkedList<>();
        supplies = new LinkedList<>();

        surfaceHolder = getHolder();
        surfaceHolder.addCallback(this);
        setFocusable(true);
        this.setKeepScreenOn(true);
        paint.setDither(true);
        paint.setAntiAlias(true);
        recordsDAO = new RecordsDaoImpl();
        //初始化难度
        if(difficultyClass == null) {
            if(ParameterSet.getInstance().getDifficulty() == 1) {
                backgroundBitmap = ImageManager.BACKGROUND_MEDIUM_BITMAP;
                difficultyClass = new MediumDiff();
            } else if (ParameterSet.getInstance().getDifficulty() == 2) {
                backgroundBitmap = ImageManager.BACKGROUND_HARD_BITMAP;
                difficultyClass = new HardDiff();
            } else {
                backgroundBitmap = ImageManager.BACKGROUND_EASY_BITMAP;
                difficultyClass = new EasyDiff();
            }
        }
        executorService = new ScheduledThreadPoolExecutor(2);

        //音乐服务绑定
        this.context = context;
        Connect connection = new Connect();
        Intent intent = new Intent(context, MusicService.class);
        context.bindService(intent, connection, Context.BIND_AUTO_CREATE);
    }

    @Override
    public void surfaceCreated(@NonNull SurfaceHolder surfaceHolder) {
        isDrawing = true;
        //将任务加入线程池
        executorService.scheduleWithFixedDelay(this, timeInterval, timeInterval, TimeUnit.MILLISECONDS);
    }

    @Override
    public void surfaceChanged(@NonNull SurfaceHolder surfaceHolder, int i, int i1, int i2) {
        width = MainActivity.width;
        height = MainActivity.height;
    }


    @Override
    public void surfaceDestroyed(@NonNull SurfaceHolder surfaceHolder) {
        isDrawing = false;
        stopBgm();
    }

    @Override
    public void run() {
        if (isDrawing) {
            //进行逻辑的处理
            action();
            //进行图片的绘制
            draw();
        }
    }


    private void draw() {
        try {
            canvas = surfaceHolder.lockCanvas();

            synchronized (surfaceHolder) {
                // 这里进行内容的绘制
                // 绘制背景,图片滚动
                canvas.drawBitmap(backgroundBitmap, 0, backgroundTop - backgroundBitmap.getHeight(), paint);
                canvas.drawBitmap(backgroundBitmap, 0, backgroundTop, paint);
                backgroundTop += 5;
                if (backgroundTop >= height) {
                    backgroundTop -= backgroundBitmap.getHeight();
                }

                // 先绘制子弹和道具，后绘制飞机
                // 这样子弹显示在飞机的下层
                paintImageWithPositionRevised(supplies);

                paintImageWithPositionRevised(enemyBullets);
                paintImageWithPositionRevised(enemyAircrafts);

                paintImageWithPositionRevised(heroBullets);
                if(boomingThread != null && boomingThread.isAlive()) {
                    Bitmap bitmap = ImageManager.BOOM_BITMAP;
                    canvas.drawBitmap(bitmap, (int)(boomingTimeController.getLocationX() - bitmap.getWidth() / 2.0), (int)(boomingTimeController.getLocationY() - bitmap.getHeight() / 2.0), paint);
                }

                heroAircraft.draw(canvas,paint);
                if(heroAircraft.getHp() <= 0) {
                    heroAircraft.drawDestroyed(canvas,paint);

                }
                //绘制得分和生命值
                paintScoreAndLife();
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        surfaceHolder.unlockCanvasAndPost(canvas);
    }
    /**
     * 绘画图片
     * */
    private void paintImageWithPositionRevised(List<? extends AbstractFlyingObject> objects)
    {
        if (objects == null || objects.size() == 0) {
            return;
        }
        for (int i = 0; i < objects.size(); i++) {
            if(objects.get(i).notValid()) {
                objects.get(i).drawDestroyed(canvas,paint);
            } else {
                objects.get(i).draw(canvas,paint);
            }
        }
        //移除无效飞行物
        objects.removeIf(AbstractFlyingObject::notValid);
    }




    private void paintScoreAndLife() {
        int x = 30;
        int y = 75;
        Paint text = new Paint();
        text.setColor(Color.RED);
        text.setTextSize(50);
        text.setAntiAlias(true);
        canvas.drawText("SCORE:" + score, x, y, text);
        y += 50;
        canvas.drawText("LIFE:" + heroAircraft.getHp(), x, y, text);

        if(ParameterSet.getInstance().isOnline) {
            y += 100;
            text.setTextSize(64);
            canvas.drawText("OPPONENT SCORE:" + ParameterSet.opponentScore, x, y, text);
        }
    }


    /**
     * 游戏启动入口，执行游戏逻辑
     */
    public void action()  {
        // 定时任务：绘制、对象产生、碰撞判定、击毁及结束判定
            scoreIncrease = 0;
            time += timeInterval;
            playBgm(ParameterSet.INSTANCE.getHasBoss());
            if(ParameterSet.getInstance().noElite()) {
                timeWithoutElite += timeInterval;
            } else {
                timeWithoutElite = 0;
            }
            // 周期性执行（控制频率）
            if (timeCountAndNewCycleJudge()) {
                // 新敌机产生
                AbstractAircraft aircraft = null;
                if(boomingThread == null || !boomingThread.isAlive()){
                    aircraft = difficultyClass.runDifficultySystem(time, enemyAircrafts.size(),timeWithoutElite,score);
                }
                if(aircraft != null) {
                    enemyAircrafts.add(aircraft);
                }
                cycleDuration = ParameterSet.getInstance().getNewCycleDuration();
                // 飞机射出子弹
                shootAction();
            }

            // 子弹移动
            bulletsMoveAction();

            // 飞机移动
            aircraftsMoveAction();

            // 补给移动
            suppliesMoveAction();

            // 撞击检测
            crashCheckAction();

            // 后处理
            postProcessAction();

            if(scoreIncrease > 0) {
                score += scoreIncrease;
                if(ParameterSet.INSTANCE.isOnline) {
                    MyWsManager.getInstance().sendData(String.valueOf(score));
                }
            }

            // 游戏结束检查
            if (heroAircraft.getHp() <= 0) {

                if(ParameterSet.INSTANCE.getSound()){
                    myBinder.playMusic(5);
                }

                //得到积分
                int point = ParameterSet.INSTANCE.getPoint();
                int increase = (score/20) * ParameterSet.INSTANCE.getDifficulty();
                if(ParameterSet.INSTANCE.pointDouble) {
                    increase *= 2;
                }

                stopBgm();
                //结束绘画
                this.surfaceDestroyed(this.getHolder());
                //记录分数
                Record record = new Record(score,ParameterSet.getInstance().getName());
                try {
                    recordsDAO.addRecord(record);
                }catch (IOException e){
                    e.printStackTrace();
                }
                Message msg = Message.obtain();
                msg.what = 1;
                msg.arg1 = (point + increase);
                msg.obj  = score;
                handler.sendMessage(msg);

            }
    }
    //***********************
    //      Action 各部分
    //***********************

    private boolean timeCountAndNewCycleJudge() {
        cycleTime += timeInterval;
        if (cycleTime >= cycleDuration) {
            // 跨越到新的周期
            cycleTime %= cycleDuration;
            return true;
        } else {
            return false;
        }
    }

    private void shootAction() {
        // TODO 敌机射击
        if(boomingThread == null || !boomingThread.isAlive()){
            for(AbstractAircraft enemyAircraft : enemyAircrafts) {
                enemyBullets.addAll(enemyAircraft.shoot(enemyAircraft));
            }
        }
        // 英雄射击
        heroBullets.addAll(heroAircraft.shoot(heroAircraft));
        if(ParameterSet.INSTANCE.getSound()){
            myBinder.playMusic(2);
        }
    }

    private void bulletsMoveAction() {
        int enemySize = enemyAircrafts.size();
        AbstractAircraft aircraft = null;
        for (AbstractBullet bullet : heroBullets) {
            if(bullet instanceof TrackBullet) {
                if(enemySize > 0) {
                    Random random = new Random();
                    aircraft = enemyAircrafts.get(random.nextInt(enemySize));
                }
                ((TrackBullet) bullet).aiming(aircraft);
            }
            bullet.forward();
        }
        for (AbstractBullet bullet : enemyBullets) {
            bullet.forward();
        }
    }

    private void aircraftsMoveAction() {
        for (AbstractAircraft enemyAircraft : enemyAircrafts) {
            enemyAircraft.forward();
        }
    }

    private void suppliesMoveAction() {
        for (AbstractSupply supply : supplies) {
            supply.forward();
        }
    }

    private void createSupply(int locationX, int locationY){
        double luck = Math.random();
        Creator creator;
//        if(luck > ParameterSet.getInstance().getFireSupplyRange()) {
        if(true) {
            creator = new FireSupplyCreator();
            supplies.add((AbstractSupply) creator.creatObject(locationX, locationY));
        }
        else if(luck > ParameterSet.getInstance().getBombSupplyRange()) {
            creator = new BombSupplyCreator();
            supplies.add((AbstractSupply) creator.creatObject(locationX, locationY));
        }
        else if(luck > ParameterSet.getInstance().getHpSupplyRange()) {
            creator = new HpSupplyCreator();
            supplies.add((AbstractSupply) creator.creatObject(locationX, locationY));
        }
    }
    /**
     * 碰撞检测：
     * 1. 敌机攻击英雄
     * 2. 英雄攻击/撞击敌机
     * 3. 英雄获得补给
     */
    private void crashCheckAction() {
        // TODO 敌机子弹攻击英雄
        for (int i = 0; i < enemyBullets.size(); ++i) {
            if (enemyBullets.get(i).notValid()) {
                continue;
            }
            if(heroAircraft.crash(enemyBullets.get(i))) {
                heroAircraft.decreaseHp(enemyBullets.get(i).getPower());
                enemyBullets.get(i).vanish();
                if(ParameterSet.INSTANCE.getSound()){
                    myBinder.playMusic(1);
                }
            }
        }
        // 英雄子弹攻击敌机
        for (int i = 0; i < heroBullets.size(); ++i) {
            AbstractBullet bullet = heroBullets.get(i);
            if(heroBullets.get(i) instanceof MissileBoom) {
                heroBullets.get(i).vanish();
                continue;
            }
            if (bullet.notValid()) {
                continue;
            }
            for (AbstractAircraft enemyAircraft : enemyAircrafts) {
                if (enemyAircraft.notValid()) {
                    continue;
                }
                if(bullet.crash(enemyAircraft)) {
                    // 敌机撞击到英雄机子弹
                    // 敌机损失一定生命值
                    enemyAircraft.decreaseHp(bullet.getPower());
                    if(ParameterSet.INSTANCE.getSound()){
                        myBinder.playMusic(1);
                    }
                    bullet.vanish();
                }
                // 英雄机 与 敌机 相撞，均损毁
                if (enemyAircraft.crash(heroAircraft) || heroAircraft.crash(enemyAircraft)) {
                    enemyAircraft.vanish();
                    heroAircraft.decreaseHp(Integer.MAX_VALUE);
                }
            }
        }
        //爆炸生成
        int heroBulletSize = heroBullets.size();
        List<AbstractBullet> missileBooms = new LinkedList<>();
        for(int i = 0; i < heroBulletSize; ++i) {
            if(heroBullets.get(i) instanceof Missile && heroBullets.get(i).notValid()) {
                int locationX = heroBullets.get(i).getLocationX();
                int locationY = heroBullets.get(i).getLocationY();
                MissileBoom missileBoom = new MissileBoom(
                        locationX,
                        locationY,
                        0,0,60
                );
                missileBoom.vanish();
                missileBooms.add(missileBoom);
                for (AbstractAircraft enemyAircraft : enemyAircrafts) {
                    if(enemyAircraft.crash(missileBoom)) {
                        enemyAircraft.decreaseHp(missileBoom.getPower());
                    }
                }
            }
        }
        for (AbstractAircraft enemyAircraft : enemyAircrafts){
            enemyDeathProcess(enemyAircraft);
        }
        if(missileBooms.size() > 0) {
            heroBullets.addAll(missileBooms);
        }

        for(AbstractSupply supply : supplies) {
            if(heroAircraft.crash(supply)){
                if(supply instanceof FireSupply) {
                    if(fireSupplyThread != null) {
                        fireSupplyThread.setWillRestore(false);
                    }
                    fireSupplyThread = new FireSupplyThread();
                    new Thread(fireSupplyThread).start();
                } else if(supply instanceof BombSupply) {
                    for(AbstractBullet bullet : enemyBullets) {
                        ((BombSupply) supply).addObject(bullet);
                    }
                    for(AbstractAircraft aircraft : enemyAircrafts) {
                        ((BombSupply) supply).addObject(aircraft);
                    }
                    scoreIncrease += ((BombSupply) supply).notifyAllObject();
                    ParameterSet.getInstance().setHasElite(false);

                    boomingTimeController = new TimeController(1000,supply.getLocationX(),supply.getLocationY());
                    boomingThread = new Thread(boomingTimeController);
                    boomingThread.start();
                    if(ParameterSet.INSTANCE.getSound()){
                        myBinder.playMusic(4);
                    }
                } else if(supply instanceof HpSupply) {
                    supply.effectActive();
                }
                supply.vanish();
                if(ParameterSet.INSTANCE.getSound()){
                    myBinder.playMusic(3);
                }
            }
        }

    }

    /**
     * 后处理：
     * 1. 删除无效的子弹
     * 2. 删除无效的敌机
     * 3. 检查英雄机生存
     * 4. 删除无效的补给
     * <p>
     * 无效的原因可能是撞击或者飞出边界
     */
    private void postProcessAction() {
    }

    private void enemyDeathProcess(AbstractAircraft enemyAircraft){
        if (enemyAircraft.notValid()) {
            int locationX = enemyAircraft.getLocationX();
            int locationY = enemyAircraft.getLocationY();
            if(enemyAircraft instanceof EliteEnemy) {
                ParameterSet.getInstance().setHasElite(false);
                scoreIncrease += 50;
                createSupply(locationX, locationY);
            }
            else if (enemyAircraft instanceof Boss) {
                scoreIncrease += 150;
                ParameterSet.getInstance().setHasBoss(false);
                supplies.add((AbstractSupply) new BombSupplyCreator().creatObject(locationX,locationY));
            }
            else {
                scoreIncrease += 10;
            }
        }
    }
    //播放音乐
    public void playBgm(boolean hasBoss){
        if(player == null && ParameterSet.INSTANCE.getBgm()) {
            if(hasBoss) {
                player = MediaPlayer.create(context, R.raw.bgm_boss);
            } else {
                player = MediaPlayer.create(context, R.raw.bgm);
            }
            player.setLooping(true);
        } else if(this.hasBoss != hasBoss && ParameterSet.INSTANCE.getBgm()) {
            stopBgm();
            if(hasBoss) {
                player = MediaPlayer.create(context, R.raw.bgm_boss);
            } else {
                player = MediaPlayer.create(context, R.raw.bgm);
            }
            player.setLooping(true);
        }
        this.hasBoss = hasBoss;
        if(player != null) {
            player.start();
        }
    }

    public void stopBgm() {
        if (player != null) {
            player.stop();
            player.reset();//重置
            player.release();//释放
            player = null;
        }
    }

    class Connect implements ServiceConnection {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service){
            myBinder = (MusicService.MyBinder)service;
        }
        @Override
        public void onServiceDisconnected(ComponentName componentName) {

        }
    }

    public static int getScore() {
        return score;
    }
}



